#ifndef SKYID_IMAGE_H
#define SKYID_IMAGE_H

#include <png.h>
extern "C"
{
#include <jpeglib.h>
}

#include "common.h"
#include "object.h"
#include "reader.h"

#define JPEG_BUFFER_SIZE	0x1000

namespace SkyID 
{

enum ImageFormat
{
	FORMAT_UNKNOWN = 0,
	FORMAT_RGB = 3,
	FORMAT_RGBA = 4
};

//- Image ---------------------------------------------------------------------

class Image : public Object
{
public:
	Image();
	virtual ~Image();

	Image(const Image &img);
	Image& operator=(const Image &img);

	virtual bool open(Reader* reader) { return false; }

	uint32 getWidth() const { return mWidth; }
	uint32 getHeight() const { return mHeight; }
	ImageFormat getFormat() const { return mFormat; }
	const uchar* getData() const { return mData; }

protected:
	void clean();
	void createImage(uint32 width, uint32 height, ImageFormat format);
	void copyFromImage(const Image &img);

protected:
	uint32 mWidth, mHeight;
	ImageFormat mFormat;
	uchar *mData;
};

//- ImageJPEG -----------------------------------------------------------------

class ImageJPEG : public Image
{
public:
	ImageJPEG();
	ImageJPEG(Reader *reader);

	bool open(Reader* reader);

private:
	struct JpegCustomSource
	{
		jpeg_source_mgr pub;
		Reader *reader;
		JOCTET *buffer;
		bool firstCall;
	};
	static void jpegInitSource(j_decompress_ptr cinfo);
	static boolean jpegFillInputBuffer(j_decompress_ptr cinfo);
	static void jpegSkipInputData(j_decompress_ptr cinfo, long num_bytes);
	static void jpegTermSource(j_decompress_ptr cinfo);
	static void jpegSetCustomSource(j_decompress_ptr cinfo, Reader *reader);
};

//- ImagePNG ------------------------------------------------------------------

class ImagePNG : public Image
{
public:
	ImagePNG();
	ImagePNG(Reader *reader);

	bool open(Reader* reader);

private:
	static void pngError(png_structp png_ptr, png_const_charp msg);
	static void PNGAPI pngRead(png_structp png_ptr, png_bytep data, png_size_t length);
};

} // namespace SkyID

#endif // SKYID_IMAGE_H
